package com.yunhe.common.exception.handler;

import com.yunhe.common.exception.*;
import com.yunhe.common.exception.code.ErrorCode;
import com.yunhe.common.model.ResultObject;
import com.yunhe.common.util.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.URLEncoder;
import java.util.List;

/**
 * 异常处理类
 * @desc 异常处理类定义
 * @author liuronglei
 */
@ControllerAdvice
@ResponseBody
public class ExceptionHandlerAdvice {
    private static Logger logger = LoggerFactory.getLogger(ExceptionHandlerAdvice.class);

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ResultObject> handleException(MethodArgumentNotValidException e) {
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        String tips = "请求参数不合法";
        if (errors.size() > 0) {
            tips = errors.get(0).getDefaultMessage();
        }
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.METHOD_ARGUMENT_NOTVALID.value(), tips),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<ResultObject> handleException(HttpMessageNotReadableException e) {
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.METHOD_ARGUMENT_NOTVALID.value(), "请求参数无法解析，请检查参数类型"),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<ResultObject> handleException(MethodArgumentTypeMismatchException e) {
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.METHOD_ARGUMENT_NOTVALID.value(), "请求参数（或路径参数）类型错误"),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler(ArgumentErrorException.class)
    public ResponseEntity<ResultObject> handleException(ArgumentErrorException e) {
        logger.error("查询参数错误，错误信息如下：");
        e.printStackTrace();
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.ARGUMENT_ERROR.value(), e.getMessage()),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler(DatabaseProcessException.class)
    public ResponseEntity<ResultObject> handleException(DatabaseProcessException e) {
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.DATABASE_PROCESS.value(), e.getMessage()),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler(UniqueConstraintsException.class)
    public ResponseEntity<ResultObject> handleException(UniqueConstraintsException e) {
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.UNIQUE_CONSTRAINTS.value(), e.getMessage()),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler(ObjectNotFoundException.class)
    public ResponseEntity<ResultObject> handleException(ObjectNotFoundException e) {
        logger.error("找不到所需对象，错误信息如下：");
        e.printStackTrace();
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.OBJECT_NOTFOUND.value(), e.getMessage()),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler(ModelNotFoundException.class)
    public ResponseEntity<ResultObject> handleException(ModelNotFoundException e) throws UnsupportedEncodingException {
        logger.error("找不到所需对象，错误信息如下：");
        e.printStackTrace();
        return ResponseEntity.status(HttpStatus.BAD_REQUEST.value()).header(
                String.valueOf(ErrorCode.CODE.OBJECT_NOTFOUND.value()), URLEncoder.encode(e.getMessage(),"UTF-8"))
                .body(new ResultObject<>(ErrorCode.CODE.OBJECT_NOTFOUND.value(), e.getMessage()));
    }



    @ExceptionHandler(LoginExpireException.class)
    public ResponseEntity<ResultObject> handleException(LoginExpireException e) {
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.LOGIN_EXPIRE.value(), e.getMessage()),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler(UsernamePasswordException.class)
    public ResponseEntity<ResultObject> handleException(UsernamePasswordException e) {
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.USERNAME_PASSWORD_ERROR.value(), e.getMessage()),
                HttpStatus.UNPROCESSABLE_ENTITY
        );
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ResultObject> handleException(Exception e) {
        logger.error(ExceptionUtil.getMessage(e));
        String meassage = "系统运行错误";
        if ("java.lang.reflect.InvocationTargetException".equals(e.getMessage())){
            meassage = e.getCause().getCause().getMessage();
        }
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.RUNTIME_EXCEPTION.value(), meassage),
                HttpStatus.BAD_REQUEST
        );
    }


    @ExceptionHandler(UndeclaredThrowableException.class)
    public ResponseEntity<ResultObject> handleException(UndeclaredThrowableException e) {
        logger.error(ExceptionUtil.getMessage(e));
        return new ResponseEntity<>(
                new ResultObject<>(ErrorCode.CODE.RUNTIME_EXCEPTION.value(), e.getUndeclaredThrowable().getMessage()),
                HttpStatus.BAD_REQUEST
        );
    }
}
